package cn.dduan.fool.features.stream;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Java Stream
 * <p>
 * 创建 Stream
 *
 * <p>
 * 中间操作：
 * 1. filter()
 * 2. map()
 * 3. flatMap()
 * 4. distinct()
 * 5. limit()
 * 6. peek()
 * 7. skip()
 * <p>
 * 终端操作：
 * 1. anyMatch()
 * 2. allMatch()
 * 3. noneMatch()
 * 4. collect()
 * 5. count()
 * 6. findAny()
 * 7. findFirst()
 * 8. forEach()
 * 9. min()
 * 10. max()
 * 11. reduct()
 * 12. toArray()
 * 13. sorted()
 *
 * 并行流：
 * 1. parallel()
 *
 * @author dduan
 * @version 1.0
 * @date 2025/3/6
 */
public class MyStream {
    public static void main(String[] args) {
        /**
         * 创建
         */
        // MyStream.createStream();

        /**
         * 中间操作
         */
        // MyStream.streamFilter();
        // MyStream.streamSorted();
        // MyStream.streamMap();
        // MyStream.streamDistinct();
        // MyStream.streamLimit();
        // MyStream.streamSkip();

        /**
         * 终端操作
         */
        // MyStream.streamMatch();
        // MyStream.streamFind();
        // MyStream.streamCount();
        // MyStream.streamReduce();
        // MyStream.streamForEach();
        // MyStream.streamCollect();
        // MyStream.streamMinOrMax();

        /**
         * 并行流
         */
        MyStream.streamParallel();

        /**
         * 数值流
         */
        MyStream.streamIntStream();

    }

    /**
     * Filter 过滤
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void createStream() {
        // 从集合创建
        List<String> list = Arrays.asList("Java", "Python", "C++");
        Stream<String> streamFromList = list.stream();

        // 从数组创建
        String[] array = {"Apple", "Banana", "Orange"};
        Stream<String> streamFromArray = Arrays.stream(array);

        // 直接创建
        Stream<String> directStream = Stream.of("One", "Two", "Three");

        // 创建无限流
        Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1); // 0, 1, 2, 3, ...
    }

    /**
     * Filter 过滤
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamFilter() {
        List<String> list = Arrays.asList("ab", "bb", "cc", "dc", "e", "1", "caomiaomiao", "yaozhijuan");
        list.stream().filter(str -> str.startsWith("cao")).forEach(System.out::println);
    }

    /**
     * Sorted 排序
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamSorted() {
        List<String> list = Arrays.asList("ab", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        list.stream().sorted().filter(str -> str.startsWith("a")).forEach(System.out::println);
    }

    /**
     * Map 转换
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamMap() {
        List<String> list = Arrays.asList("ab", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        list.stream().map(String::toUpperCase).sorted((a, b) -> b.compareTo(a)).forEach(System.out::println);
    }

    /**
     * Match 匹配
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamMatch() {
        List<String> list = Arrays.asList("ab", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        boolean b = list.stream().anyMatch(str -> str.startsWith("a"));
        System.out.println("anyMatch: " + b);

        boolean c = list.stream().allMatch(str -> str.startsWith("a"));
        System.out.println("allMatch: " + c);

        boolean d = list.stream().noneMatch(str -> str.startsWith("E"));
        System.out.println("noneMatch: " + c);
    }

    /**
     * findFirst() / findAny() 查找第一个或任意一个元素
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamFind() {
        List<String> list = Arrays.asList("ab", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        Optional<String> first = list.stream().findFirst();
        first.ifPresent(System.out::println);

        Optional<String> any = list.stream().findAny();
        any.ifPresent(System.out::println);
    }

    /**
     * Count 计数
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamCount() {
        List<String> list = Arrays.asList("ab", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        long a = list.stream().filter(str -> str.startsWith("a")).count();
        System.out.println("count: " + a);
    }

    /**
     * reduce 将 list归约成一个值
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamReduce() {
        List<String> list = Arrays.asList("ab", "ab", "abb", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        Optional<String> reduce = list.stream().sorted().reduce((k1, k2) -> k1 + "," + k2);
        reduce.ifPresent(System.out::println);

        List<Integer> list1 = Arrays.asList(1, 3, 4, 5, 234, 64, 4324, 66);
        Integer sum = list1.stream().reduce(0, Integer::sum);
        Integer max = list1.stream().reduce(0, Integer::max);
        System.out.println("sum: " + sum + ",max: " + max);

    }

    /**
     * distinct 去重
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamDistinct() {
        List<String> list = Arrays.asList("ab", "ab", "abb", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        List<String> collect = list.stream().distinct().collect(Collectors.toList());
        System.out.println(collect);
    }

    /**
     * limit 限制元素数量
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamLimit() {
        List<String> list = Arrays.asList("ab", "ab", "abb", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        List<String> collect = list.stream().limit(2).collect(Collectors.toList());
        System.out.println(collect);
    }

    /**
     * skip 跳过前 N 个元素
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamSkip() {
        List<String> list = Arrays.asList("ab", "ab", "abb", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        List<String> collect = list.stream().skip(1).collect(Collectors.toList());
        System.out.println(collect);
    }

    /**
     * skip 跳过前 N 个元素
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamForEach() {
        List<String> list = Arrays.asList("ab", "ab", "abb", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        list.stream().forEach(System.out::println);
    }

    /**
     * collect 将 Stream 转换为集合或其他数据结构
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamCollect() {
        List<String> list = Arrays.asList("ab", "ab", "abb", "abb", "acc", "adc", "e", "1", "caomiaomiao", "yaozhijuan");
        List<String> collect = list.stream().filter(str -> str.length() > 2).collect(Collectors.toList());
        System.out.println(collect);
    }

    /**
     * min / max 查找最小或最大值
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamMinOrMax() {
        List<Integer> list = Arrays.asList(1, 3, 4, 5, 234, 64, 4324, 66);
        Optional<Integer> min = list.stream().min(Integer::compareTo);
        min.ifPresent(System.out::println);

        Optional<Integer> max = list.stream().max(Integer::compareTo);
        max.ifPresent(System.out::println);
    }

    /**
     * parallel 并行处理
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamParallel() {
        List<String> languages = Arrays.asList("Java", "Python", "C++", "JavaScript");
        List<String> result = languages.parallelStream()
                .filter(lang -> lang.length() > 3)
                .collect(Collectors.toList());
        System.out.println(result); // 输出: [Java, Python, JavaScript]
    }

    /**
     * IntStream、LongStream、DoubleStream 避免装箱拆箱的开销
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/6
     */
    private static void streamIntStream() {
        IntStream intStream = IntStream.range(1, 5); // 1, 2, 3, 4
        int sum = intStream.sum();
        System.out.println(sum); // 输出: 10
    }


}
